/**
 * @file datagramBuffer.h
 * @brief Fichero de cabeceras de la biblioteca auxiliar de Nivel 2.
 *
 * Fichero que contiene las cabeceras de las funciones de la
 * biblioteca auxiliar de Nivel 2, para la gestion del buffer circular
 * de datagramas.
 */

#include <stdlib.h>
#include "msgData.h"
#include "nivel1a.h"

#ifndef DATAGRAM_BUFFER_H
#define DATAGRAM_BUFFER_H

typedef struct _datagramBuffer *DATAGRAM_BUFFER;							/*!< Buffer circular de datagramas, auxiliar, para el protocolo HDLC*/

typedef enum{ITERATION_OK, ITERATION_END, ITERATION_ERR} ITERATION_STATE;	/*!< Estado de la iteracion del buffer de datagramas*/

/**
* @brief Inicializa el buffer de datagramas para almacenar size mensajes.
*
* @param size Numero maximo de mensajes a insertar en el buffer de datagramas.
* @return DATAGRAM_BUFFER creado, NULL si error.
*/
DATAGRAM_BUFFER iniDatagramBuffer(size_t size);

/**
* @brief Limpia la ultima entrada del buffer, en sentido FIFO.
*
* @param buff Buffer sobre el que ejecutar la limpieza.
* @return OK si correcto, ERR si error.
*/
ERR_CODE cleanEntryDatagramBuffer(DATAGRAM_BUFFER buff);

/**
* @brief Limpia el buffer buff hasta la entrada last (Contabilizada como
* buffer circular explicito), exclusive.
*
* @param buff Buffer sobre el que ejecutar la limpieza.
* @param last Indice de la ultima entrada a conservar, contabilizado como buffer circular.
* @return OK si correcto, ERR si error.
*/
ERR_CODE cleanIntervalDataDatagramBuffer(DATAGRAM_BUFFER buff, int last);

/**
* @brief Limpia completamente el buffer de datagramas, reiniciandolo por completo.
*
* Nota: Esta operacion no libera los recursos reservados. Para desalocar la memoria,
* llamese a freeDatagramBuffer.
*
* @param buff Buffer sobre el que ejecutar la limpieza.
*/
void cleanDatagramBuffer(DATAGRAM_BUFFER buff);

/**
* @brief Libera el buffer circular, desalocando los recursos requisados.
*
* @param buff Buffer sobre el que ejecutar la liberacion.
*/
void freeDatagramBuffer(DATAGRAM_BUFFER buff);

/**
* @brief Inserta un datagrama en el buffer.
*
* Nota: Por robustez, el buffer efectua una copia de los datos.
* Por tanto, tras la insercción, los datos parametro pueden ser manipulados libremente
* sin comprometer la coherencia del buffer.
*
* @param buff Buffer sobre el que ejecutar la insercion.
* @param datagram Array de byte's del mensaje a insertar.
* @param datagramSize Tamanno del datagrama a insertar.
* @return OK si correcto, FULL si completo, ERR si error.
*/
ERR_CODE insertDatagramBuffer(DATAGRAM_BUFFER buff, BYTE *datagram, int datagramSize);

/**
* @brief Deshace la ultima operacion de insercion ejecutada en el buffer.
*
* @param buff Buffer sobre el que ejecutar la operacion deshacer.
* @return OK si correcto ERR si error.
*/
ERR_CODE undo(DATAGRAM_BUFFER buff);

/**
* @brief Retorna el indice de la cabeza del buffer.
*
* @param buff Buffer sobre el que ejecutar la consulta.
* @return Indice consultado.
*/
int getHeadDatagramBuffer(DATAGRAM_BUFFER buff);

/**
* @brief Retorna el indice de la cola del buffer.
*
* @param buff Buffer sobre el que ejecutar la consulta.
* @return Indice consultado.
*/
int getTailDatagramBuffer(DATAGRAM_BUFFER buff);

/**
* @brief Retorna el tamanno total del buffer circular, incluyendo la entrada
* expurea introducida por coherencia estructural.
*
* @param buff Buffer sobre el que ejecutar la consulta.
* @return Tamanno consultado.
*/
size_t getTotalSizeDatagramBuffer(DATAGRAM_BUFFER buff);

/**
* @brief Retorna el numero de datagramas insertados en el buffer.
*
* @param buff Buffer sobre el que ejecutar la consulta.
* @return Tamanno consultado.
*/
size_t getSizeDatagramBuffer(DATAGRAM_BUFFER buff);

/**
* @brief Extrae un datagrama en el buffer.
*
* Nota: Por robustez, el buffer efectua una copia de los datos.
* Por tanto, tras la insercción, los datos parametro pueden ser manipulados libremente
* sin comprometer la coherencia del buffer.
* Tras la extraccion, se eliminan los datos del buffer.
*
* @param buff Buffer sobre el que ejecutar la extraccion.
* @param dst MSG_DATA destino de la extraccion.
* @return OK si correcto, EMPTY si vacio, ERR si error.
*/
ERR_CODE extractDatagramBuffer(DATAGRAM_BUFFER buff, MSG_DATA dst);

/**
* @brief Retorna si el buffer esta completo.
*
* @param buff Buffer sobre el que ejecutar la consulta.
* @return 1 si lleno, 0 si no.
*/
short isFullDatagramBuffer(DATAGRAM_BUFFER buff);

/**
* @brief Retorna si el buffer esta vacio.
*
* @param buff Buffer sobre el que ejecutar la consulta.
* @return 1 si vacio, 0 si no.
*/
short isEmptyDatagramBuffer(DATAGRAM_BUFFER buff);

/**
* @brief Reinicia el iterador.
*
* Nota: Es necesario reiniciar el iterador antes de cada
* iteracion. Solo se garantiza una iteracion simultanea.
*
* @param buff Buffer sobre el que ejecutar el reinicio.
*/
void restartIteratorDatagramBuffer(DATAGRAM_BUFFER buff);

/**
* @brief Itera sobre el buffer, copiando un datagrama a dst.
*
* Nota: Por robustez, el buffer efectua una copia de los datos.
* Por tanto, tras la insercción, los datos parametro pueden ser manipulados libremente
* sin comprometer la coherencia del buffer.
*
* @param buff Buffer sobre el que ejecutar la iteracion.
* @param dst MSG_DATA destino de la extraccion.
* @return ITERATION_OK si correcto, ITERATION_END si la iteracion ha finalizado (Se
* ha alcanzado la cabeza), ITERATION_ERR si error.
*/
ITERATION_STATE iterateDatagramBuffer(DATAGRAM_BUFFER buff, MSG_DATA dst);

#endif
